﻿using System;
using System.Data;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Configuration;

/// <summary>
/// Manage backup mechanism for artefacts
/// </summary>
public class BackupManager
{
    /// <summary>Size of sliding window of backuped files (files conserved)</summary>
    private static int maxSlidingBackup;

    public static bool BackupAutomatic;


    /// <summary>File path to be backuped </summary>
    private string targetPath;

    /// <summary> Static C'tor</summary>
    static BackupManager()
    {
        // Find backup sliding size in config
        try
        {
            string sizeStr = ConfigurationManager.AppSettings["SlidingBackupSize"].Trim();
            maxSlidingBackup = Convert.ToInt16(sizeStr);
        }
        catch
        {
            maxSlidingBackup = 5;
        }
        
        //Is backup fully automatic or on demand
        try
        {
            BackupAutomatic =Convert.ToBoolean(ConfigurationManager.AppSettings["AutomaticBackup"]);
        }
        catch { BackupAutomatic = false; }

    }

    /// <summary>Constructor</summary>
    /// <param name="path">The artefact file path</param>
    public BackupManager(string path)
    {
        targetPath = path;
    }

    public BackupManager(string arType, string fullId)
    {
        targetPath = Manager.Instance.RootPath + arType + "\\" + fullId + ".xml";

    }

    /// <summary>
    /// Backup artefact target, adapt incremental number and sliding frame
    /// </summary>
    public void DoBackup()
    {
        // Does file exist
        if (File.Exists(targetPath))
        {
            // Get next back number
            int backNb = NewBackupIndex();

            // Make backup copy by renaming
            File.Move(targetPath, CreateBackupPath(backNb));

            // do we need to erase older backup no more in sliding window
            if (backNb > maxSlidingBackup)
            {
                // Get index of backup to erase
                int nb = backNb - maxSlidingBackup;
                try
                {
                    // erase it
                    string outBackup = CreateBackupPath(nb);
                    if (File.Exists(outBackup))
                        File.Delete(outBackup);
                }catch{}
            }
        }
    }

    /// <summary>Create backup file path</summary>
    /// <param name="nb">backup extension number</param>
    /// <returns>the backup path</returns>
    public string CreateBackupPath(int nb)
    {
        StringBuilder sb = new StringBuilder(Path.GetDirectoryName(targetPath));
        sb.Append(Path.DirectorySeparatorChar).Append(Path.GetFileNameWithoutExtension(targetPath)).Append(".bak.").Append(nb);
        return sb.ToString();
    }

    public void ClearAllBackup()
    {
       // get list of existing backup
        string[] fList = GetBackupList();
        foreach (string f in fList)
        {
            try
            {
                File.Delete(f);
            }
            catch { }
        }

    }

    /// <summary>Defines new backup number</summary>
    /// <returns>the new backup number to use</returns>
    private int NewBackupIndex()
    {
        // Assume none
        int nb = 1;

        // get list of existing backup
        string[] fList = GetBackupList();
        if (fList.Length > 0)
        {
            // Get extension list (numeric)
            List<string> extList = new List<string>(maxSlidingBackup);
            foreach (string f in fList)
                extList.Add(Path.GetExtension(f).Trim('.'));
            
            // sort list
            extList.Sort(delegate(string p1, string p2)
            { return Convert.ToInt32(p1).CompareTo(Convert.ToInt32(p2)); });

            // Create next number
            nb = Convert.ToInt32(extList[extList.Count - 1]) + 1;
        }

        return nb;
    }

    /// <summary>Get list of backuped files</summary> <returns>The list</returns>
    public string[] GetBackupList()
    {
        return Directory.GetFiles(Path.GetDirectoryName(targetPath), 
            string.Format("{0}.bak.*", Path.GetFileNameWithoutExtension(targetPath)));
    }

    public DataSet GetArtefactBackupList(string arType,
        string fullId)
    {
        DataSet dsReturn = null;

        #region Create datable for backup version

        DataTable dtBackup = new DataTable();
        dtBackup.Columns.Add(new DataColumn("ARTEFACT_TYPE", System.Type.GetType("System.String")));
        dtBackup.Columns.Add(new DataColumn("FULLID", System.Type.GetType("System.String")));
        dtBackup.Columns.Add(new DataColumn("VERSION_NUMBER", System.Type.GetType("System.Int32")));
        dtBackup.Columns.Add(new DataColumn("VERSION_DATE", System.Type.GetType("System.DateTime")));
        #endregion

        // Populate the datatable
        string[] fList = GetBackupList();
        foreach (string f in fList)
        {
            DataRow backupRow = dtBackup.NewRow();
            backupRow["ARTEFACT_TYPE"] = arType;
            backupRow["FULLID"] = fullId;
            backupRow["VERSION_NUMBER"] = Convert.ToInt32(Path.GetExtension(f).Trim('.'));
            backupRow["VERSION_DATE"] = File.GetLastAccessTime(f); ;
            dtBackup.Rows.Add(backupRow);
        }

        if (dtBackup.Rows.Count > 0)
        {
            dsReturn = new DataSet();
            dsReturn.Tables.Add(dtBackup);
        }
        return (dsReturn);
    }


}
